const https = require('https');
const fs = require('fs');
const path = require('path');

/**
 * 微信公众号 Access Token 获取工具类
 */
class WeChatTokenManager {
    constructor(appId, appSecret) {
        this.appId = appId;
        this.appSecret = appSecret;
        this.tokenFile = path.join(__dirname, 'access_token.json');
        this.token = null;
        this.expiresTime = 0;
    }

    /**
     * 获取 Access Token
     * @returns {Promise<string>} Access Token
     */
    async getAccessToken() {
        try {
            // 先尝试从本地文件读取token
            if (await this.loadTokenFromFile()) {
                return this.token;
            }

            // 如果本地没有或已过期，从微信服务器获取新token
            return await this.fetchNewToken();
        } catch (error) {
            console.error('获取Access Token失败:', error);
            throw error;
        }
    }

    /**
     * 从本地文件加载token
     * @returns {Promise<boolean>} 是否成功加载有效token
     */
    async loadTokenFromFile() {
        try {
            if (!fs.existsSync(this.tokenFile)) {
                return false;
            }

            const data = fs.readFileSync(this.tokenFile, 'utf8');
            const tokenData = JSON.parse(data);
            
            // 检查token是否过期（提前5分钟刷新）
            if (Date.now() < tokenData.expiresTime - 300000) {
                this.token = tokenData.access_token;
                this.expiresTime = tokenData.expiresTime;
                console.log('从本地文件加载Access Token成功');
                return true;
            }
            
            return false;
        } catch (error) {
            console.log('读取本地token文件失败:', error.message);
            return false;
        }
    }

    /**
     * 从微信服务器获取新的Access Token
     * @returns {Promise<string>} Access Token
     */
    async fetchNewToken() {
        return new Promise((resolve, reject) => {
            const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`;
            
            console.log('正在从微信服务器获取新的Access Token...');
            
            https.get(url, (res) => {
                let data = '';
                
                res.on('data', (chunk) => {
                    data += chunk;
                });
                
                res.on('end', () => {
                    try {
                        const result = JSON.parse(data);
                        
                        if (result.errcode) {
                            reject(new Error(`微信API错误: ${result.errcode} - ${result.errmsg}`));
                            return;
                        }
                        
                        this.token = result.access_token;
                        this.expiresTime = Date.now() + (result.expires_in * 1000);
                        
                        // 保存token到本地文件
                        this.saveTokenToFile();
                        
                        console.log('获取Access Token成功');
                        resolve(this.token);
                    } catch (error) {
                        reject(new Error('解析微信API响应失败: ' + error.message));
                    }
                });
            }).on('error', (error) => {
                reject(new Error('请求微信API失败: ' + error.message));
            });
        });
    }

    /**
     * 保存token到本地文件
     */
    saveTokenToFile() {
        try {
            const tokenData = {
                access_token: this.token,
                expiresTime: this.expiresTime,
                updateTime: new Date().toISOString()
            };
            
            fs.writeFileSync(this.tokenFile, JSON.stringify(tokenData, null, 2));
            console.log('Access Token已保存到本地文件');
        } catch (error) {
            console.error('保存token到文件失败:', error);
        }
    }

    /**
     * 强制刷新token
     * @returns {Promise<string>} 新的Access Token
     */
    async refreshToken() {
        console.log('强制刷新Access Token...');
        return await this.fetchNewToken();
    }

    /**
     * 检查token是否有效
     * @returns {boolean} token是否有效
     */
    isTokenValid() {
        return this.token && Date.now() < this.expiresTime - 300000;
    }

    /**
     * 获取token剩余有效时间（秒）
     * @returns {number} 剩余秒数
     */
    getTokenRemainingTime() {
        if (!this.token) return 0;
        return Math.max(0, Math.floor((this.expiresTime - Date.now()) / 1000));
    }
}

// 使用示例
async function example() {
    // 请替换为您的实际AppID和AppSecret
    const APP_ID = 'your_app_id_here';
    const APP_SECRET = 'your_app_secret_here';
    
    const tokenManager = new WeChatTokenManager(APP_ID, APP_SECRET);
    
    try {
        // 获取Access Token
        const token = await tokenManager.getAccessToken();
        console.log('当前Access Token:', token);
        console.log('Token剩余有效时间:', tokenManager.getTokenRemainingTime(), '秒');
        
        // 可以在其他地方使用这个token进行微信API调用
        // 例如：发送模板消息、创建菜单等
        
    } catch (error) {
        console.error('示例运行失败:', error);
    }
}

// 导出类供其他模块使用
module.exports = WeChatTokenManager;

// 如果直接运行此文件，执行示例
if (require.main === module) {
    example();
}
